//
// Created by 李传智 on 2018/4/14.
//

#include "FFResample.h"
#include "Logger.h"

extern "C" {
#include <libswresample/swresample.h>
#include <libavcodec/avcodec.h>
}

bool FFResample::open(CodecParameter in, CodecParameter out) {

    close();

    mutex.lock();
    // 初始化音频重采样上下文
    swrContext = swr_alloc_set_opts(0, av_get_default_channel_layout(out.channels),
                                    (AVSampleFormat) out.format,
                                    out.sampleRate,
                                    in.parameters->channel_layout,
                                    (AVSampleFormat) in.parameters->format,
                                    in.parameters->sample_rate,
                                    0, 0);
    int ret = swr_init(swrContext);
    if (ret != 0) {
        LOG_E("swr_init failed, error = %d", ret);
        mutex.unlock();
        return false;
    }
    LOG_I("swr_init success");

    this->outParameter = out;
    mutex.unlock();

    return true;
}

void FFResample::close() {
    mutex.lock();
    if (swrContext) {
        swr_close(swrContext);
        swr_free(&swrContext);
    }
    mutex.unlock();
}

VideoData FFResample::resample(VideoData src) {

    VideoData dst;
    mutex.lock();
    if (!swrContext) {
        mutex.unlock();
        return dst;
    }
    if (src.size <= 0) {
        mutex.unlock();
        return dst;
    }

    // 分配输出空间
    int size = av_samples_get_buffer_size(0,
                                          this->outParameter.channels,
                                          src.nbSamples,
                                          (AVSampleFormat) this->outParameter.format,
                                          1);
    dst.alloc(size);
    // 输出缓冲区
    uint8_t *out[2] = {0};
    out[0] = dst.data;
    int length = swr_convert(swrContext,
                             out,
                             src.nbSamples,
                             (const uint8_t **) src.src,
                             src.nbSamples);

    //LOG_I("resample length = %d", length);

    if (length <= 0) {
        dst.free();
        mutex.unlock();
        return dst;
    }

    dst.pts = src.pts;
    mutex.unlock();

    return dst;
}